﻿// Copyright (c) MichaConrad. All rights reserved. See License.txt in the project root for license information.

namespace LinqToLdapExtensions.Tests.Scope
{
    using System;
    using System.Diagnostics.CodeAnalysis;

    using LinqToLdapExtensions.Scope;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented",
        Justification = "Reviewed. Suppression is OK here.")]
    [TestClass]
    public class UnitOfWorkTest
    {
        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void ThreadStaticUnitOfWorkThrowsIfEndBeforeBeginGetsCalled()
        {
            var factory = TestHelper.MockFactory(ScopeState.ThreadStatic);

            var unitOfWork = new DirectoryContextUnitOfWork(factory);

            unitOfWork.EndUnitOfWork();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void ThreadStaticUnitOfWorkThrowsIfBeginGetsCalledTwice()
        {
            var factory = TestHelper.MockFactory(ScopeState.ThreadStatic);

            var unitOfWork = new DirectoryContextUnitOfWork(factory);

            unitOfWork.BeginUnitOfWork();
            unitOfWork.BeginUnitOfWork();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void ThreadStaticUnitOfWorkThrowsIfBeginAfterManuallyUnbind()
        {
            var factory = TestHelper.MockFactory(ScopeState.ThreadStatic);

            var unitOfWork = new DirectoryContextUnitOfWork(factory);

            unitOfWork.BeginUnitOfWork();
            CurrentDirectoryContext.Unbind(factory);
            unitOfWork.EndUnitOfWork();
        }

        [TestMethod]
        public void ThreadStaticUnitOfWorkValidateCurrentContext()
        {
            var factory = TestHelper.MockFactory(ScopeState.ThreadStatic);

            var unitOfWork = new DirectoryContextUnitOfWork(factory);

            unitOfWork.BeginUnitOfWork();
            Assert.IsNotNull(unitOfWork.CurrentContext);
            Assert.IsNotNull(unitOfWork.Factory);
            unitOfWork.EndUnitOfWork();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WebUnitOfWorkThrowsIfEndBeforeBeginGetsCalled()
        {
            TestHelper.MockHttpContext();

            var factory = TestHelper.MockFactory(ScopeState.WebContext);

            var unitOfWork = new DirectoryContextUnitOfWork(factory);

            unitOfWork.EndUnitOfWork();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WebUnitOfWorkThrowsIfBeginGetsCalledTwice()
        {
            TestHelper.MockHttpContext();

            var factory = TestHelper.MockFactory(ScopeState.WebContext);

            var unitOfWork = new DirectoryContextUnitOfWork(factory);

            unitOfWork.BeginUnitOfWork();
            unitOfWork.BeginUnitOfWork();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WebUnitOfWorkThrowsIfBeginAfterManuallyUnbind()
        {
            TestHelper.MockHttpContext();

            var factory = TestHelper.MockFactory(ScopeState.WebContext);

            var unitOfWork = new DirectoryContextUnitOfWork(factory);

            unitOfWork.BeginUnitOfWork();
            CurrentDirectoryContext.Unbind(factory);
            unitOfWork.EndUnitOfWork();
        }

        [TestMethod]
        public void WebUnitOfWorkValidateCurrentContext()
        {
            TestHelper.MockHttpContext();

            var factory = TestHelper.MockFactory(ScopeState.WebContext);

            var unitOfWork = new DirectoryContextUnitOfWork(factory);

            unitOfWork.BeginUnitOfWork();
            Assert.IsNotNull(unitOfWork.CurrentContext);
            Assert.IsNotNull(unitOfWork.Factory);
            unitOfWork.EndUnitOfWork();
        }
    }
}
